#include "Logger.h"
#include "Appender.h"
#include <stdio.h>
#include <stdarg.h>

namespace phnq
{
	namespace kit
	{
		namespace log
		{
			static short globalLevel = Logger::DEBUG;
			
			static vector<Logger*> all;
			
			Logger* Logger::get(string category)
			{
				Logger *logger = new Logger(category);
				all.push_back(logger);
				return logger;
			}

			void Logger::setGlobalLevel(short level)
			{
				globalLevel = level;
			}

			Logger::Logger(string category)
			{
				this->category = category;
				this->appender = StdOutAppender::getInstance();
			}
			
			string Logger::getCategory()
			{
				return this->category;
			}
			
			void Logger::setAppender(Appender *appender)
			{
				this->appender = appender;
			}

			void Logger::critical(const char *msg, ...)
			{
				if(globalLevel >= CRITICAL)
				{
					va_list argList;
					va_start(argList, msg);
					write(CRITICAL, 0, msg, argList);
					va_end(argList);
				}
			}
			
			void Logger::critical(LoggerTime start, const char *msg, ...)
			{
				if(globalLevel >= CRITICAL)
				{
					LoggerTime t = clock() - start;
					va_list argList;
					va_start(argList, msg);
					write(CRITICAL, t, msg, argList);
					va_end(argList);
				}
			}
			
			void Logger::error(const char *msg, ...)
			{
				if(globalLevel >= ERROR)
				{
					va_list argList;
					va_start(argList, msg);
					write(ERROR, 0, msg, argList);
					va_end(argList);
				}
			}

			void Logger::error(LoggerTime start, const char *msg, ...)
			{
				if(globalLevel >= ERROR)
				{
					LoggerTime t = clock() - start;
					va_list argList;
					va_start(argList, msg);
					write(ERROR, t, msg, argList);
					va_end(argList);
				}
			}
			
			void Logger::warning(const char *msg, ...)
			{
				if(globalLevel >= WARNING)
				{
					va_list argList;
					va_start(argList, msg);
					write(WARNING, 0, msg, argList);
					va_end(argList);
				}
			}

			void Logger::warning(LoggerTime start, const char *msg, ...)
			{
				if(globalLevel >= WARNING)
				{
					LoggerTime t = clock() - start;
					va_list argList;
					va_start(argList, msg);
					write(WARNING, t, msg, argList);
					va_end(argList);
				}
			}
			
			void Logger::info(const char *msg, ...)
			{
				if(globalLevel >= INFO)
				{
					va_list argList;
					va_start(argList, msg);
					write(INFO, 0, msg, argList);
					va_end(argList);
				}
			}

			void Logger::info(LoggerTime start, const char *msg, ...)
			{
				if(globalLevel >= INFO)
				{
					LoggerTime t = clock() - start;
					va_list argList;
					va_start(argList, msg);
					write(INFO, t, msg, argList);
					va_end(argList);
				}
			}
			
			void Logger::debug(const char *msg, ...)
			{
				if(globalLevel >= DEBUG)
				{
					va_list argList;
					va_start(argList, msg);
					write(DEBUG, 0, msg, argList);
					va_end(argList);
				}
			}
			
			void Logger::debug(LoggerTime start, const char *msg, ...)
			{
				if(globalLevel >= DEBUG)
				{
					LoggerTime t = clock() - start;
					va_list argList;
					va_start(argList, msg);
					write(DEBUG, t, msg, argList);
					va_end(argList);
				}
			}

			LoggerTime Logger::time()
			{
				return clock();
			}

			void Logger::write(short level, LoggerTime t, const char *msg, va_list &argList)
			{
				vsprintf(lineBuf, msg, argList);
				this->appender->append(this, level, t, lineBuf);
			}
		}
	}
}
